#pragma once

#include "sock.h"
#include <string>
#include <pthread.h>
#include <fstream>
#include <vector>

class httpserver;
const std::string room = "./room";

class threadData
{
public:
    threadData(int fd, const std::string& ip, uint16_t port, httpserver* t)
        : _sockfd(fd), _ip(ip), _port(port), _t(t)
    { }
public:
    int _sockfd;
    std::string _ip;
    uint16_t _port;
    httpserver* _t;
};

//反序列化
class httpRequset
{
public:
    httpRequset(const std::string& req)
    {
        Deserialize(req);
    }
    void Deserialize(const std::string& req)
    {
        std::string sep = "\r\n";
        size_t pos = 0;
        size_t findi = req.find(sep, pos);
        while(findi != std::string::npos)
        {
            _head.push_back(req.substr(pos, findi - pos));
            pos = findi + 2;
            findi = req.find(sep, pos);
        }
        _text = req.substr(pos);

        geturl(_head[0]);
    }
    void geturl(const std::string& head)
    {
        size_t pos1 = head.find(" ");
        size_t pos2 = head.find(" ", pos1 + 1);
        _url = head.substr(pos1 + 1, pos2 - pos1 - 1);
    }
    void Debug()
    {
        for(auto& s : _head)
        {
            std::cout << s << std::endl;
        }
        std::cout << _text << std::endl;
        std::cout << _url << std::endl;
    }
public:
    std::vector<std::string> _head;
    std::string _text;

    std::string _url;
};

class httpserver
{
public:
    httpserver(uint16_t port) : _port(port)
    {
        _listensocket.Socket();
        _listensocket.Bind(_port);
        _listensocket.Listen();
    }
    void Start()
    {
        std::cout << "start now..." << std::endl;
        while(true)
        {
            std::string clientip;
            uint16_t clientport;
            int sockfd = _listensocket.Accept(clientip, clientport);
            if(sockfd < 0)
            {
                std::cout << "Accept error" << std::endl;
                continue;
            }
            std::cout << "Accept over..." << std::endl;
            threadData* Data = new threadData(sockfd, "", 0, this);
            pthread_t tid;
            pthread_create(&tid, nullptr, threadHandler, Data);
        }
    }
    std::string readHtmltext(const std::string& Path)
    {
        std::string readpath;
        if(Path == "/")
            readpath = room + "/home.html";
        else
            readpath = room + Path;
        std::fstream fd(readpath, std::ios::in);
        std::string out;
        if(fd.is_open())
        {
            std::string tmp;
            while(std::getline(fd, tmp))
            {
                out += tmp;
                out += "\r\n";
            }
            fd.close();
        }
        else
        {
            std::fstream in("./room/404.html", std::ios::in);
            std::string tmp;
            while(std::getline(in, tmp))
            {
                out += tmp;
            }
            in.close();
        }
        return out;
    }
    void httpHandler(int fd)
    {
        std::cout << "The fd is: " << fd << "..." << std::endl;
        char buffer[10240]{0};
        ssize_t n = recv(fd, buffer, sizeof(buffer) - 1, 0);
        if(n > 0)
        {
            //std::cout << buffer << std::endl;
            httpRequset Req(buffer);
            Req.Debug();
            
            std::string text = readHtmltext(Req._url);
            std::string message = "HTTP/2.0 200 OK\r\n";
            message += "Content-Length: ";
            message += std::to_string(text.size()) + "\r\n";
            message += "\r\n";
            message += text;
            std::cout << message << std::endl;
            send(fd, message.c_str(), message.size(), 0);
        }
        close(fd);
    }
    static void* threadHandler(void* args)
    {
        pthread_detach(pthread_self());
        threadData* td = (threadData*)args;
        td->_t->httpHandler(td->_sockfd);
        delete td;
        return nullptr;
    }
private:
    Sock _listensocket;
    uint16_t _port;
};
